context
现在公司的项目中,有两个界面表现几乎完全一样的控制器.如图:
但是两者的行为是部分有差别的,当时编码过程中,遵循了极限编程
的原则,尽快的写出可以实现功能的代码. 重构和使用模式的工作放在以后进行 . 以防止过度设计
带来的问题.
写好一个界面之后,直接复制代码,修改了部分.这在什么时候来看,都是编写的最快方式,但是却不是好的设计和可维护方案.
所以现在要开始进行重构了.
初始代码
下面是两个类之一的完整代码 .您不用完整阅读,因为在后面,我会逐一分解之:
GUIResetPasswordController.h
文件
1 | #import <UIKit/UIKit.h> |
GUIPhoneNumberModificationController.m
文件
1 |
|
重构代码
发现代码的问题
- 首先,文件本身没有结构,阅读需要翻来翻去. 利用 Code Snippets 添加固定结构到文件顶部:
1 |
|
方法分门别类放好,最后可以从这里看到代码的结构了.
关于这么组织的点子和原因,来源于这篇文章
我要还补充一点,就是对使用 xvim 插件的开发者们, 这方法是在爽爆了,当你在 viewDidLoad
中编写代码,需要一个新方法的时候,只需要:
- 切换到命令模式 (我已经映射成了 zz)
- 按
/
输入你想写的方法的 mark ,比如private
,回车 - 按
o
一个熟练的 vim 使用者,整个过程也就2秒钟 ,那代码在你眼前飞动的感觉呦 ~
下面回归正题
代码的不合理之处
从第一个方法 viewDidLoad
开始往下看
1 | #pragma mark -life cycle |
似乎没有什么问题, 如果有强迫症可以把设置背景色提取一个方法.提取方法的原则是:你想给代码写注释了 ,那么就把代码放到方法中,给方法起个意图明显的名字,哪怕只有一行代码 ! (因为注释都是邪恶的,不解释)
但是我觉得这里没有什么阅读困难,所以不去提取方法.
然后下一行 [self setupChildViews];
,点击进去. okay,出现问题代码了.
1 |
|
这个方法违背了单一职责原则
.就是一个方法做了太多事情. 下面通过 提取方法
的重构手法进行重构.
最终代码:
1 |
|
关于对变量命名的改进,我待会自己做了,就不写出来了
通过重构,整个结构变得清爽. 但是有出现了一个新问题: 在 viewDidLoad
中对 setupChildViews
的调用显得有点不平衡(个人觉得),更重要的原因,以后我要采用模板方法
这个模式,过深的调用层级,子类重写方法的时候,需要开发者过多精力.所以,我采用 内联方法
将函数的实现放到调用函数的地方.
删除 setupChildViews
,将实现放到 viewDidLoad
中
1 | - (void)viewDidLoad { |
到此,我觉得方法就这样吧. 接下来找变量的问题. 第一眼看到的就是两个宏:
1 | #define kLeftViewWidth (40) |
记得在哪里读过 ,在值替换上使用宏是一个不好的习惯(宏有自己不可替换的功能,这里不做讨论).因为有全局变量可以实现它的功能,更重要的是编译器会对全局变量的类型等进行检查,降低出错的几率.
所以修改如下:
1 | static CGFloat const kLeftViewHeight = 40; |
结语
好了,重构篇就先到此了, 可以肯定的是,这样去做模板方法
模式,是不够的,因为没有隔离出变化.但是我准备把这项工作放到下一篇中,毕竟要先遇到问题,再去解决问题才是好的做法